跳转至

重构 1995 年的 GPS 时间服务器:免遭澳洲电信(Telstra)式的故障波及

文章背景与核心概要

本文记录了作者购买一台1995年出产的古董级 TrueTime XL-AK 时间服务器并对其进行“现代复古改装”(Restomod)的过程。就在作者购入不久后,澳大利亚发生了一起类似的 GPS 时间服务器故障,导致全国蜂窝网络中断长达 12 小时。为了让这台老旧硬件重获新生并兼具实用性,作者将一台运行 Stratum 1 NTP 时间服务器的树莓派 5(Raspberry Pi 5)、GNSS 扩展板、时间/日间协议、AppleTalk 支持,以及原机的 Densitron 液晶显示屏和双色 LED 指示灯进行了完美集成。

通过本次改造,作者不仅让这台老式设备接入了现代网络并计划加入 NTP Pool,还通过硬件和软件的双重优化(如固定风扇占空比、隔离内核 PPS 中断等)大幅提升了授时精度。整个改造过程完全可逆,展现了极高的极客动手能力与软硬件结合水平。


引言

In June, I purchased a TrueTime XL-AK time server to learn more about the history of GPS-based time. I received it on June 22, and just 16 days later, a similar GPS time server took down Australia's cell service for 12 hours!

今年 6 月,我购买了一台 TrueTime XL-AK 时间服务器,以深入了解基于 GPS 的时间同步历史。我在 6 月 22 日收到了它,而仅仅 16 天后,一台类似的 GPS 时间服务器导致澳大利亚的蜂窝网络瘫痪了 12 个小时

TrueTime XL-AK with Pi inside running Densitron LCD

TrueTime XL-AK with Pi inside running Densitron LCD

Over the past couple of weeks, I "restomodded" this device with a Raspberry Pi to build a Stratum 1 NTP Time server, which I eventually plan to add to the NTP Pool. I found a way to drop in a Pi 5 and GNSS HAT, display the time and GPS status on the built-in 16x2 LCD, show status via the bicolor LED, and make this box useful again.

在过去的几周里,我用树莓派对这款设备进行了“现代复古改装”(Restomod),将其打造成一个 Stratum 1 NTP 时间服务器,并计划最终将其加入 NTP Pool。我找到了一种方法,将树莓派 5 和 GNSS 扩展板塞进机箱,在内置的 16x2 LCD 上显示时间和 GPS 状态,通过双色 LED 展示运行状态,让这个老旧的铁盒再次焕发光彩。

In this post, I'll walk through how I configured the Raspberry Pi as a Stratum 1 NTP time server using: * Jimmy Paputto's L1 GNSS HAT * Chrony (for time synchronization and NTP services) * Time and Daytime Protocols * A built-in Densitron LCD * The TrueTime's built-in bicolor LED * My TrueTime Pi Mounting Bracket

在这篇文章中,我将详细介绍如何使用以下组件将树莓派配置为 Stratum 1 NTP 时间服务器: * Jimmy Paputto 的 L1 GNSS HAT * Chrony(用于时间同步和 NTP 服务) * Time 和 Daytime 协议 * 内置的 Densitron LCD * TrueTime 内置的双色 LED * 我的 TrueTime 树莓派安装支架


Jimmy Paputto L1 GNSS HAT

Jimmy Paputto L1 GNSS HAT outputting a 1 PPS signal on handheld oscilloscope

Jimmy Paputto L1 GNSS HAT outputting a 1 PPS signal on handheld oscilloscope

I mounted the GNSS HAT on top of the Pi using the included GPIO riser and mounting screws, securing a Raspberry Pi Bumper underneath.

我使用随附的 GPIO 增高柱和安装螺丝将 GNSS 扩展板安装在树莓派上方,并在底部固定了一个树莓派防撞胶垫(Raspberry Pi Bumper)

After flashing Raspberry Pi OS 'Lite' (no GUI) to a microSD card, I built the Jimmy Paputto GNSS HAT software from source:

在将 Raspberry Pi OS 'Lite'(无图形界面)烧录到 microSD 卡后,我从源码编译了 Jimmy Paputto GNSS HAT 的软件:

sudo apt -y install build-essential cmake libgpiod-dev python3-dev
git clone https://github.com/jimmypaputto/gnsshat.git
cd gnsshat
mkdir -p build && cd build
cmake .. -DBUILD_PYTHON=ON -DBUILD_EXAMPLES=ON
make -j$(nproc)
sudo make install

This software includes a data bridge to transfer NMEA sentences to gpsd and chrony. Once installed, I followed the guide to set up a Raspberry Pi Time Server with PPS.

该软件包含一个数据桥接器,用于将 NMEA 语句传输到 gpsdchrony。安装完成后,我按照指南设置了带 PPS 的树莓派时间服务器


Chrony 配置

I used the following settings inside /etc/chrony/chrony.conf:

我在 /etc/chrony/chrony.conf 中使用了以下设置:

# GNSS + PPS time server

# GPS time via shared memory from gpsd
refclock SHM 0 offset 0.0 delay 0.05 refid NMEA noselect

# PPS — precise edge timing
refclock PPS /dev/pps0 refid PPS lock NMEA prefer trust poll 3 filter 16

# The Pi's XO is fairly stable, but not quite TCXO-level.
maxclockerror 0.5 

# Hardware timestamping for more precision on Pi 5
hwtimestamp *

# Fallback internet pools
pool 0.pool.ntp.org iburst
pool 1.pool.ntp.org iburst

# Allow all LAN clients
allow 10.0.0.0/16

# Allow requests routed through Twingate container.
allow 172.17.0.0/16

maxupdateskew 100.0
makestep 1000 3
rtcsync

# Ignore clock updates >100ms (fixes gpsd reporting time 1s off every ~31 min)
maxchange 0.1 1 -1

Restart chrony after updating:

更新后重启 chrony

sudo systemctl restart chrony

Verify everything is working with:

使用以下命令验证各项功能是否正常:

chronyc sources -v
chronyc tracking

树莓派授时微调

To stabilize the oscillator frequency, I implemented several hardware and software adjustments: 1. Running the fan at a constant duty cycle. 2. Forcing the Pi's SoC to run full speed using force_turbo. 3. Pinning the kernel PPS interrupts to CPU core 4 (after isolating that core). 4. Insulating the bottom of the Pi to maintain a stable thermal environment for the crystal. 5. Enclosing the Pi within the TrueTime chassis.

为了稳定晶振频率,我实施了多项硬件和软件调整: 1. 使风扇以恒定占空比运行。 2. 使用 force_turbo 强制树莓派的 SoC 全速运行。 3. 将内核 PPS 中断绑定到 CPU 核心 4(在隔离该核心之后)。 4. 对树莓派底部进行绝缘处理,以为晶振保持稳定的热环境。 5. 将树莓派封闭在 TrueTime 机箱内部。

稳定的树莓派时钟

Stable Pi Clock

Add the following to /boot/firmware/config.txt and reboot:

将以下内容添加到 /boot/firmware/config.txt 并重启:

# Force performance governor so CPU maintains a more stable temperature.            
force_turbo=1

稳定的风扇转速

Consistent Fan Speed

Airflow fluctuations (such as HVAC systems) can cause the Pi's crystal oscillator to drift. Using a large heatsink, bottom-insulation, and a locked fan duty cycle helped stabilize the frequency.

气流波动(例如 HVAC 系统的影响)会导致树莓派的晶振发生漂移。使用大型散热片、底部绝缘以及锁定的风扇占空比有助于稳定频率。

在单 CPU 核心上隔离 PPS 中断

Isolating PPS Interrupts on a Single CPU Core

To achieve more deterministic PPS handling: 1. Edit /boot/firmware/cmdline.txt and add isolcpus=3 to the options. 2. Reboot the system. 3. Create /usr/local/sbin/pin-pps-irq.sh (chmod +x it):

为了实现更具确定性的 PPS 处理: 1. 编辑 /boot/firmware/cmdline.txt,在选项中加入 isolcpus=3。 2. 重启系统。 3. 创建 /usr/local/sbin/pin-pps-irq.sh 并赋予其执行权限 (chmod +x):

#!/bin/sh
irq=$(awk '/pps@/ {sub(":","",$1); print $1}' /proc/interrupts)
[ -n "$irq" ] && echo 3 > /proc/irq/$irq/smp_affinity_list
  1. Create /etc/systemd/system/pin-pps-irq.service:
  1. 创建 /etc/systemd/system/pin-pps-irq.service
[Unit]
Description=Pin PPS GPIO IRQ to isolated CPU3
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/pin-pps-irq.sh

[Install]
WantedBy=multi-user.target
  1. Enable and start the service: sudo systemctl enable --now pin-pps-irq.service.
  1. 启用并启动该服务:sudo systemctl enable --now pin-pps-irq.service

监控与物理时间显示

TrueTime Pi Chrony Monitoring Dashboard

TrueTime Pi Chrony Monitoring Dashboard

To monitor performance, I built chrony-dashboard with assistance from Claude.

为了监控性能,我在 Claude 的协助下开发了 chrony-dashboard

For the hardware side, I mapped the GPIO pins to the vintage Densitron LCD using densitron-lcd.

在硬件方面,我使用 densitron-lcd 将 GPIO 引脚映射到了复古的 Densitron 液晶显示屏上。

Wire Wrapping on pins on a perfboard

Wire Wrapping on pins on a perfboard

Because of vertical clearance limits inside the chassis, I used wire wrapping rather than traditional dupont connectors or direct soldering. This technique creates a gas-tight electrical connection around square posts with very low resistance.

由于机箱内部垂直空间的限制,我使用了绕线(Wire Wrapping)技术,而不是传统的杜邦头或直接焊接。这种技术能够在方柱引脚周围形成气密性电气连接,且电阻极低。


附加服务与彩蛋

Time 与 Daytime 协议

Time and Daytime Protocols

As an easter egg for VCF Midwest, I also enabled RFC 867/868 Time and Daytime services:

作为献给 VCF Midwest(中西部复古电脑节)的一个彩蛋,我还启用了 RFC 867/868 的 Time 和 Daytime 服务:

sudo apt install xinetd
sudo systemctl enable xinetd
# Edit /etc/xinetd.d/time and /etc/xinetd.d/daytime to set disable to "no"
sudo systemctl restart xinetd

适用于 TimeLord 服务器的 AppleTalk / Netatalk

AppleTalk / Netatalk for TimeLord Server

Old vintage Macs can grab time across AppleTalk via timelord running inside a Docker container via netatalk:

复古的老款 Macintosh 电脑可以通过运行在 Docker 容器(通过 netatalk)内的 timelord 跨 AppleTalk 获取时间:

sudo modprobe appletalk && lsmod | grep appletalk
echo appletalk | sudo tee /etc/modules-load.d/appletalk.conf
mkdir -p ~/netatalk/afpshare

Create a docker-compose.yml file inside ~/netatalk/:

~/netatalk/ 目录下创建一个 docker-compose.yml 文件:

services:
  netatalk:
    image: netatalk/netatalk:latest
    container_name: netatalk
    restart: unless-stopped
    network_mode: host
    cap_add:
      - NET_ADMIN
    volumes:
      - ./afpshare:/mnt/afpshare
      - /var/run/dbus:/var/run/dbus
    environment:
      AFP_USER: myname
      AFP_PASS: mypass
      AFP_GROUP: afpusers
      ATALKD_INTERFACE: eth0
      INSECURE_AUTH: "1"
      AFP_EXTMAP: "1"
      DISABLE_TIMEMACHINE: "1"
      SERVER_NAME: "TrueTime Pi"
      TZ: America/Chicago

结论

TrueTime Pi mount finished with GPS jumper connected

TrueTime Pi mount finished with GPS jumper connected

The restomod is completely reversible—by simply re-plugging two internal connectors, the unit reverts entirely to its original 1995 hardware. Future plans for the build include designing a custom PCB with an SMT GPIO header for cleaner swappability and getting the original TrueTime keypad functioning to toggle through UI statistics.

这次现代复古改装是完全可逆的——只需重新插上两个内部连接器,设备就能完全恢复为 1995 年的原版硬件。该项目未来的计划包括设计一块带有 SMT GPIO 排针的定制 PCB 以实现更干净的模块化互换,并让原装的 TrueTime 键盘恢复功能,以便通过按键切换查看 UI 统计信息。